package cn.net.qinling.healthcare.test.datagen;

import java.util.List;
import java.util.Random;
import java.util.UUID;

import org.openhealthtools.mdht.uml.cda.AssignedAuthor;
import org.openhealthtools.mdht.uml.cda.AssignedCustodian;
import org.openhealthtools.mdht.uml.cda.Author;
import org.openhealthtools.mdht.uml.cda.CDAFactory;
import org.openhealthtools.mdht.uml.cda.Custodian;
import org.openhealthtools.mdht.uml.cda.CustodianOrganization;
import org.openhealthtools.mdht.uml.cda.InfrastructureRootTypeId;
import org.openhealthtools.mdht.uml.cda.Patient;
import org.openhealthtools.mdht.uml.cda.PatientRole;
import org.openhealthtools.mdht.uml.cda.Person;
import org.openhealthtools.mdht.uml.cda.SubstanceAdministration;
import org.openhealthtools.mdht.uml.cda.ccd.CCDFactory;
import org.openhealthtools.mdht.uml.cda.ccd.ContinuityOfCareDocument;
import org.openhealthtools.mdht.uml.cda.ccd.MedicationsSection;
import org.openhealthtools.mdht.uml.cda.ccd.ProblemObservation;
import org.openhealthtools.mdht.uml.cda.ccd.ProblemSection;
import org.openhealthtools.mdht.uml.hl7.datatypes.CE;
import org.openhealthtools.mdht.uml.hl7.datatypes.DatatypesFactory;
import org.openhealthtools.mdht.uml.hl7.datatypes.II;
import org.openhealthtools.mdht.uml.hl7.datatypes.ON;
import org.openhealthtools.mdht.uml.hl7.datatypes.PN;
import org.openhealthtools.mdht.uml.hl7.datatypes.TS;

import cn.net.qinling.healthcare.CDARootIdentifiers;
import cn.net.qinling.healthcare.test.datagen.PersonGenerator.PersonInfo;

public class PrescriptionGenerator extends Generator<ContinuityOfCareDocument> implements CCDGenerator {

	public PrescriptionGenerator(Selector selector) {
		super(selector);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected ContinuityOfCareDocument doGeneration() {
		ContinuityOfCareDocument ccdDocument = CCDFactory.eINSTANCE
				.createContinuityOfCareDocument().init();

		initDocumentHeader(ccdDocument);

		ccdDocument.addPatientRole(getRandomPatientRole());
		ccdDocument.getAuthors().add(getAuthor());

		ccdDocument.setCustodian(getCustodian());

		// 1. Problem List
		ProblemSection problemSection = CCDFactory.eINSTANCE
				.createProblemSection().init();
		int problemSize = getRandomSize(4);
		//System.out.println(problemSize);
		List<ProblemObservation> generatedList = problemGenerator
				.generate(problemSize);
		for (ProblemObservation po : generatedList) {
			problemSection.addObservation(po);
		}
		ccdDocument.addSection(problemSection);

		// 2. Medicine List
		MedicationsSection medicationsSection = CCDFactory.eINSTANCE
				.createMedicationsSection().init();
		int medicationSize = getRandomSize(4);
		//System.out.println(medicationSize);
		List<SubstanceAdministration> medicationsList = saGenerator
				.generate(medicationSize);
		for (SubstanceAdministration sa : medicationsList) {
			medicationsSection.addSubstanceAdministration(sa);
		}
		ccdDocument.addSection(medicationsSection);

		return ccdDocument;
	}

	private PersonGenerator personGenerator = new PersonGenerator(selector);

	private ProblemGenerator problemGenerator = new ProblemGenerator(selector);

	private SubstanceAdministrationGenerator saGenerator = new SubstanceAdministrationGenerator(
			selector);

	private AddressGenerator addressGenerator = new AddressGenerator(selector);

	private OrganizationGenerator organizationGenerator = new OrganizationGenerator(
			selector);

	private Random random = new Random();

	private int getRandomSize(int maxSize) {
		int result = random.nextInt(maxSize);
		if (0 == result) {
			result = 1;
		}

		return result;
	}

	private void fillDocumentID(ContinuityOfCareDocument ccdDocument) {
		II did = DatatypesFactory.eINSTANCE.createII();
		did.setRoot(CDARootIdentifiers.DOCUMENT_ID);
		did.setExtension(getRandomUUID());
		ccdDocument.setId(did);
	}

	private void fillDocumentType(ContinuityOfCareDocument ccdDocument) {
		InfrastructureRootTypeId rti = CDAFactory.eINSTANCE
				.createInfrastructureRootTypeId();
		rti.setExtension("POCD_HD000040");
		ccdDocument.setTypeId(rti);

		CE ce = DatatypesFactory.eINSTANCE.createCE();
		ce.setCode("B0007");
		ce.setDisplayName("处方记录");
		ce.setCodeSystem(CDARootIdentifiers.DOCUMENT_TYPE);
		ce.setCodeSystemName("卫生信息共享文档分类编码系统");
		ccdDocument.setCode(ce);
	}

	private void fillDocumentTemplate(ContinuityOfCareDocument ccdDocument) {
		II templateId = DatatypesFactory.eINSTANCE.createII();
		templateId.setRoot("SD.10.1");
		templateId.setExtension("DT2011001");
		templateId.setAssigningAuthorityName("处方记录");
		ccdDocument.getTemplateIds().clear();
		ccdDocument.getTemplateIds().add(templateId);
	}

	private void initDocumentHeader(ContinuityOfCareDocument ccdDocument) {
		fillDocumentID(ccdDocument);
		fillDocumentType(ccdDocument);
		fillDocumentTemplate(ccdDocument);

		ccdDocument.setTitle(DatatypesFactory.eINSTANCE.createST("处方记录"));
		ccdDocument.getRealmCodes().add(
				DatatypesFactory.eINSTANCE.createCS("CN"));
		ccdDocument.setEffectiveTime(DatatypesFactory.eINSTANCE
				.createTS(TimeUtil.getRandomTime("yyyyMMddhhmmss")));
		ccdDocument.setConfidentialityCode(DatatypesFactory.eINSTANCE.createCE(
				"N", "2.16.840.1.113883.5.25"));
	}

	private Custodian getCustodian() {
		Custodian custodian = CDAFactory.eINSTANCE.createCustodian();
		CustodianOrganization corg = CDAFactory.eINSTANCE
				.createCustodianOrganization();
		corg.getIds().add(
				DatatypesFactory.eINSTANCE.createII(
						CDARootIdentifiers.CUSTODIAN_ORGANIZATION, "9999999"));
		ON orgName = DatatypesFactory.eINSTANCE.createON();
		orgName.addText("医疗数据测试中心");
		corg.setName(orgName);
		AssignedCustodian assignedCustodian = CDAFactory.eINSTANCE
				.createAssignedCustodian();
		assignedCustodian.setRepresentedCustodianOrganization(corg);
		custodian.setAssignedCustodian(assignedCustodian);
		return custodian;
	}

	private Author getAuthor() {
		Author author = CDAFactory.eINSTANCE.createAuthor();
		AssignedAuthor aauthor = CDAFactory.eINSTANCE.createAssignedAuthor();

		author.setTime(DatatypesFactory.eINSTANCE.createTS(TimeUtil
				.getRandomTime(-2, "yyyyMMddhhmmss")));
		aauthor.getIds().add(
				DatatypesFactory.eINSTANCE.createII(CDARootIdentifiers.AUTHOR,
						this.getRandomUUID()));
		aauthor.setAssignedPerson(getRandomPerson());
		aauthor.setRepresentedOrganization(organizationGenerator.generate());
		author.setAssignedAuthor(aauthor);

		return author;
	}

	private PatientRole getRandomPatientRole() {
		PatientRole result = CDAFactory.eINSTANCE.createPatientRole();
		Patient patient = CDAFactory.eINSTANCE.createPatient();

		PersonInfo personInfo = personGenerator.generate();
		result.getIds().add(
				DatatypesFactory.eINSTANCE.createII(
						CDARootIdentifiers.PERSON_ID_CARD, personInfo.getId()));

		// create an address object and add it to patient role
		result.getAddrs().add(addressGenerator.generate());
		PN name = DatatypesFactory.eINSTANCE.createPN();
		patient.getNames().add(name);
		name.addGiven(personInfo.getFirstName());
		name.addFamily(personInfo.getLastName());

		CE administrativeGenderCode = DatatypesFactory.eINSTANCE.createCE();

		patient.setAdministrativeGenderCode(administrativeGenderCode);
		administrativeGenderCode.setCode(personInfo.getGender());
		administrativeGenderCode.setCodeSystem("2.16.840.1.113883.5.1");

		TS birthTime = DatatypesFactory.eINSTANCE.createTS();
		patient.setBirthTime(birthTime);
		birthTime.setValue(personInfo.getDob());

		result.setPatient(patient);

		return result;
	}

	private Person getRandomPerson() {
		Person person = CDAFactory.eINSTANCE.createPerson();
		PN pn = DatatypesFactory.eINSTANCE.createPN();

		PersonGenerator.PersonInfo pi = personGenerator.generate();
		pn.addGiven(pi.getFirstName());
		pn.addFamily(pi.getLastName());
		person.getNames().add(pn);

		return person;
	}

	private String getRandomUUID() {
		return UUID.randomUUID().toString();
	}

}
